var Background;

(function () {
    var instance;

    Background = function () {
        var settings, subscriptions, feed, feedContent, loadFeed, interval,
                previousPeriod, errorHandler, tabID, updateIcon, notifications,
                linearizer, feedLinearContent, notifyUser,
                feedsLoadingProgress, oauth, deletedVideosMemory;

        if (instance) {
            return instance;
        }
        instance = this;

        settings = new Settings();
        subscriptions = new Subscriptions();
        feed = new Feed();
        feedContent = {};
        feedLinearContent = [];
        notifications = new Notifications();
        linearizer = new FeedLinearizer();
        feedsLoadingProgress = {};
        oauth = new OAuth2();
        deletedVideosMemory = new DeletedVideosMemory();

        this.requestOAuthAuthorization = function (callback) {
            var uri;
            uri = "https://gdata.youtube.com/feeds/api/users/default/" +
                    "subscriptions";
            oauth.get(uri, {}, callback, callback);
        };

        this.getWithOAuth = function (url, params, callback, errCallback) {
            oauth.get(url, params, callback, errCallback);
        };

        this.getFeedsLoadingProgress = function () {
            return feedsLoadingProgress;
        };

        /**
         * @param {String} channel Name of the YouTube channel.
         * @param {Boolean} status true if the feed has been loaded successfuly
         */
        this.setFeedLoadingProgress = function (channel, status) {
            feedsLoadingProgress[channel] = status;
        };

        this.resetFeedLoadingProgress = function () {
            feedsLoadingProgress = {};
        };

        /**
         * @return {Boolean} true if all feeds has been loaded successfuly.
         */
        this.getFeedLoadingResult = function () {
            var i;
            for (i in feedsLoadingProgress) {
                if (!feedsLoadingProgress[i]) {
                    return false;
                }
            }
            return true;
        };

        /**
         * Initializes the feed loading progress status object with the
         * specified list of subscription youtube channels.
         */
        this.initFeedLoadingProgress = function (subscriptions) {
            var i;
            for (i = subscriptions.length; i--;) {
                feedsLoadingProgress[subscriptions[i]] = false;
            }
        };

        this.reload = function () {
            settings.reload();
            deletedVideosMemory.reload();
            subscriptions.flushCache();
            updateIcon();
            loadFeed();
            if (settings.getPollingPeriod() != previousPeriod) {
                previousPeriod = settings.getPollingPeriod();
                clearInterval(interval);
                interval = setInterval(loadFeed, settings.getPollingPeriod() *
                        1000);
            }
        };

        this.getFeed = function () {
            return settings.getPrimarySort() ? feedLinearContent : feedContent;
        };

        this.getTabID = function () {
            return tabID;
        };

        this.setTabID = function (newTabID) {
            tabID = newTabID;
        };

        errorHandler = function (xhr) {
            // TODO
        };

        loadFeed = function () {
            subscriptions.loadSubscriptions(function (subs) {
                feed.loadFeed(subs, function (videos) {
                    feedContent = videos;
                    feedLinearContent = linearizer.linearize(feedContent);
                    updateIcon();
                    notifyUser();
                }, errorHandler);
            }, errorHandler);
        };

        updateIcon = function () {
            var newVideos;
            newVideos = deletedVideosMemory.filterFeed(feedLinearContent);
            chrome.browserAction.setBadgeText({
                text: newVideos.length ? newVideos.length.toString() : ''
            });
        };

        notifyUser = function () {
            var length, video, newVideos, lastTime;
            newVideos = deletedVideosMemory.filterFeed(feedLinearContent);
            length = newVideos.length;
            if (length) {
                video = newVideos[length - 1];
                lastTime = settings.getLastNotifiedVideoTime();
                if ((video.id != settings.getLastNotifiedVideo()) &&
                        (video.uploaded > lastTime)) {
                    notifications.create(video,
                            settings.getNotificationTimeout());
                    settings.setLastNotifiedVideo(video.id);
                    settings.setLastNotifiedVideoTime(video.uploaded);
                }
            }
        };

        loadFeed();
        previousPeriod = settings.getPollingPeriod();
        interval = setInterval(loadFeed, settings.getPollingPeriod() * 1000);

        chrome.tabs.onRemoved.addListener(function (id, info) {
            if (tabID == id) {
                tabID = undefined;
            }
        });

        return instance;
    };
}());

addEventListener('DOMContentLoaded', function () {
    new Background();
}, false);
